#coding=utf-8
import re

#_underscorer1 = re.compile(r'(.)([A-Z][a-z]+)')
#_underscorer2 = re.compile('([a-z0-9])([A-Z])')

# def camel_to_snake(s):
#     """
#     Is it ironic that this function is written in camel case, yet it
#     converts to snake case? hmm..
#     """
#     subbed = _underscorer1.sub(r'\1_\2', s)
#     print(subbed)
#     return _underscorer2.sub(r'\1_\2', subbed).lower()

# def snake_to_camel(s):
#     """
#     """
#     pass

def camel_to_underscore(name):
    """
    Convert a name from camel case convention to underscore lower case convention.
    Args: name (str): name in camel case convention.
    Returns: name in underscore lowercase convention.
    """
    camel_pat = re.compile(r'([A-Z])')
    return camel_pat.sub(lambda x: '_' + x.group(1).lower(), name)


def underscore_to_camel(name):
    """
    Convert a name from underscore lower case convention to camel case convention.
    Args: name (str): name in underscore lowercase convention.
    Returns: Name in camel case convention.
    """
    under_pat = re.compile(r'_([a-z])')
    return under_pat.sub(lambda x: x.group(1).upper(), name)


def change_dict_naming_convention(d, convert_function):
    """
    Convert a nested dictionary from one convention to another.
    Args:
    d (dict): dictionary (nested or not) to be converted.
    convert_function (func): function that takes the string in one convention and returns it in the other one.
    Returns:Dictionary with the new keys.
    """
    new = {}
    for k, v in d.items():
        new_v = v
        if isinstance(v, dict):
            new_v = change_dict_naming_convention(v, convert_function)
        elif isinstance(v, list):
            new_v = list()
            for x in v:
                new_v.append(change_dict_naming_convention(x, convert_function))
        new[convert_function(k)] = new_v
    return new
